from sqlobject import SQLObject, DateTimeCol, IntCol, BoolCol, StringCol, MultipleJoin, ForeignKey, RelatedJoin
from datetime import datetime, timedelta
from twisted.web import xmlrpc
from twisted.python import log

class Persistent( SQLObject ):
    
    class sqlmeta:
        pass

    creation_time       = DateTimeCol( default = DateTimeCol.now )
    modified_time       = DateTimeCol( default = DateTimeCol.now )
    
    def updateModifiedTime(self, new_datetime = None ):
        if not new_datetime:
            new_datetime = DateTimeCol.now()
            
        self.modified_time = new_datetime
        
class XMLRPCServerConfig( Persistent ):
    
    http_port = IntCol( default = 8080 )
    config_refresh_interval = IntCol( default = 60 )
    
    enable_ssl = BoolCol( default = False )
    ssl_key = StringCol( default = '' )
    ssl_certificate = StringCol( default = '' )
    
class DNSServerConfig( Persistent ):
    
    class sqlmeta:
        pass
    
    udp_port    = IntCol( default = 1053 )
    tcp_port    = IntCol( default = 1053 )
    
    deny_inactive_ips = BoolCol( default = False )
    
    active_list_refresh_interval    = IntCol( default = 6 )
    config_refresh_interval     = IntCol( default = 60 )
    
    auth_name   = StringCol( default='' )
    
    resolvers = MultipleJoin( 'DNSResolver', joinColumn = 'config_id' )
    
class DNSResolver( SQLObject ):
    hostname = StringCol( length = 50, notNone = True )
    port = IntCol( default = 53 )
    
    config = ForeignKey( 'DNSServerConfig' )
    
class Environment( Persistent ):
    name    = StringCol( length = 100, unique = True, alternateID = True )
    
    redirected_rrs  = MultipleJoin( 'ResourceRecord' )
    
class ResourceRecord( Persistent ):
    name    = StringCol( length = 100, alternateID = True )
    ttl     = IntCol()
    type    = StringCol( length = 10 )
    klass   = StringCol( length = 10 )
    value   = StringCol( length = 100 )
    
    environment = ForeignKey('Environment')

class Party( Persistent ):
    name = StringCol( length = 100, unique = True, alternateID = True )
    
    users = RelatedJoin( 'User', addRemoveName = 'User' )
    admins = RelatedJoin( 'User', addRemoveName = 'Admin', intermediateTable = 'party_admin' )

    active_checkouts = MultipleJoin( 'Checkout' )

class User( Persistent ):
    name        = StringCol( length = 100, unique = True, alternateID = True )
    password    = StringCol( length = 20 )
    admin       = IntCol( default = 0 )
    
    ip_address = StringCol( default = '' )
    ip_address_modified_time = DateTimeCol( default = None )
    
    party = RelatedJoin( 'Party' )
    
class Checkout( Persistent ):        
    environment         = ForeignKey('Environment', unique = True )
    checkout_time       = DateTimeCol( default = datetime.now() )
    expiration_time     = DateTimeCol( default = datetime.now() + timedelta( days = 1 ) )
    party               = ForeignKey('Party', cascade = True )


""" Common Functions
    Mostly used to clean up redundant error checking and reporting code
"""
def getCheckoutById( checkout_id ):
        try:
            checkout = Checkout.get( checkout_id )
        except IndexError:
            raise xmlrpc.Fault( 123, 'checkout not found' )
        except:
            log.err( 'could not retrieve checkout. checkout_id: %d' % checkout_id )
            log.err()
            raise xmlrpc.Fault( 123, 'could not retrieve checkout' )
        
        return checkout
    
def getPartyById( party_id ):
        try:
            party = Party.get( party_id )
        except IndexError:
            raise xmlrpc.Fault( 123, 'party not found' )
        except:
            log.err( 'could not retrieve party. party_id: %d' % party_id )
            log.err()
            raise xmlrpc.Fault( 123, 'could not retrieve party' )
        
        return party
    
def getUserById( user_id ):
        try:
            user = User.get( user_id )
        except IndexError:
            raise xmlrpc.Fault( 123, 'user not found' )
        except:
            log.err( 'could not retrieve user. user_id: %d' % user_id )
            log.err()
            raise xmlrpc.Fault( 123, 'could not retrieve user' )
        
        return user

def getEnvironmentById( environment_id ):
        try:
            env = Environment.get( int( environment_id ) )
        except IndexError:
            raise xmlrpc.Fault( 123, 'environment not found' )
        except:
            log.err( 'could not retrieve environment. environment_id: %d' % environment_id )
            log.err()
            raise xmlrpc.Fault( 123, 'could not retrieve environment' )
        
        return env

def getIPAddressById( ip_id ):
        try:
            ip = IPAddress.get( int( ip_id ) )
        except IndexError:
            raise xmlrpc.Fault( 123, 'ip not found' )
        except:
            log.err( 'could not retrieve ip. ip_id: %d' % ip_id )
            log.err()
            raise xmlrpc.Fault( 123, 'could not retrieve ip' )
        
        return ip

def getResourceRecordById( rr_id ):
        try:
            rr = ResourceRecord.get( int( rr_id ) )
        except IndexError:
            raise xmlrpc.Fault( 123, 'resource record not found' )
        except:
            log.err( 'could not retrieve resource record. rr_id: %d' % rr_id )
            log.err()
            raise xmlrpc.Fault( 123, 'could not retrieve resource record' )
        
        return rr